package cn.com.jrj.base.work;

import java.util.Date;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import EDU.oswego.cs.dl.util.concurrent.Semaphore;
import cn.com.jrj.base.exception.ApplicationException;
import cn.com.jrj.base.util.DateUtil;
import cn.com.jrj.base.util.VelocityUtil;

public abstract class VnetAppWork {
	
	protected final Log log = LogFactory.getLog(getClass());

	protected final Log eventLog = LogFactory.getLog("workevent");

	private final Semaphore available = new Semaphore(1);

	protected ThreadPoolTaskExecutor taskExecutor;

	protected int cnt; // 记录执行的次数

	protected VelocityUtil velocityUtil;
 
	
	public void execute(Map<String, Object> params) {
		Date start = null;
		Date end = null;
		try {
			// 判断任务是否为系统初始化级的任务
			available.permits();
			cnt++;
			start = new Date();
			executeInternal(params);
		} catch (ApplicationException e) {
			log
					.error(getClass().getName()
							+ "#execute ApplicationException", e);
		} catch (Exception e) {
			log.error(getClass().getName() + "#execute Exception", e);
		} finally {
			available.release(); // 释放
			end = new Date();
		}
		if (eventLog.isInfoEnabled()) {
			String format = "yy/MM/dd HH:mm:ss";
			StringBuffer sb = new StringBuffer();
			sb.append(getClass().getSimpleName()).append(" #execute at ");
			sb.append("[").append(DateUtil.getInstance().format(start, format))
					.append(" - ").append(
							DateUtil.getInstance().format(end, format)).append(
							"]");
			sb.append(" cnt:").append(cnt);
			eventLog.info(sb.toString());
		}
	}
	/**
	 * 如果此任务没有执行，则丢弃此任务
	 */
	public void discard() {
		if (log.isInfoEnabled())
			log.info("==========" + getClass().getName() + "  is discarded at "
					+ DateUtil.getInstance().formatAll(new Date()));
	}

	protected abstract void executeInternal(Map<String, Object> params)
			throws ApplicationException, InterruptedException;
	public VelocityUtil getVelocityUtil() {
		return velocityUtil;
	}
	public void setVelocityUtil(VelocityUtil velocityUtil) {
		this.velocityUtil = velocityUtil;
	}
	
	public ThreadPoolTaskExecutor getTaskExecutor() {
		return taskExecutor;
	}

	public void setTaskExecutor(ThreadPoolTaskExecutor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}

	public boolean attempt() throws InterruptedException {
		return available.attempt(10);
	}

}
